<html>
  <head>
    <title></title>
    <style>
    
    widget[type="auto-complete"] {
      prototype:AutoComplete;
      display:block;
      flow:stack;
      border:1dip solid red;
      padding:2dip;
      width:8em;
      font:system;
    }
    widget[type="auto-complete"] > input,
    widget[type="auto-complete"] > span { 
      background: none;
      border:none;
      padding:1dip;
      margin:0;
      display:block;
      height:1.2em;
      width:*
    }
    
    widget[type="auto-complete"] > span {
      color:#ccc;
      cursor:text;
    }
    widget[type="auto-complete"] > popup {
      width:*;
      height:min-content;
      display:none;
      background:infobackground;
      border:1px solid black;
    }

    widget[type="auto-complete"] > popup > text {
      behavior:clickable;  // generates click events
    }

    widget[type="auto-complete"] > popup > text:hover {
      background:highlight;
      color:highlighttext;
    }

    
    </style>
    <script type="text/tiscript">

      class AutoComplete : Element {
      
        function attached() {
          this.candidate = this.$(span);
          this.input = this.$(input);
          this.candidates = this.$(popup);
        }

        event change $(input) { this.onTextChange(); }
        event change $(mouseup) { this.input.state.focus = true; }
        event click  $(popup>text) (evt,elText) { this.setText(elText.text, elText.attributes["data-id"]) }
        
        function onTextChange()
        {
          var text = this.input.value;
          if( text )
          {
            var caretPos = this.input.selectionStart();
            this.input.value = text = text.toUpperCase();
            this.input.setSelection(caretPos,caretPos); 
            var list = this.getCandidates(text);
            this.candidates.clear();
            for(var li in list) 
              this.candidates.$append(<text data-id="{li.id}">{li.text}</text>);
            this.candidate.text = list.length ? list[0].text : "";
            this.popup( this.candidates , (8 << 16) | 2);
            this.input.state.focus = true;
          }
          else {
            this.candidates.state.popup = false;
            this.candidate.value = "";
          }
            
        }
        
        function getCandidates(forText) {
        
          var pattern = forText + "*";
        
          return [
            {text:"ABCDEF", id:1 },
            {text:"ABFOO", id:2 },
            {text:"BCDEFG", id:3 },
            {text:"BCDEFGH", id:4 },
            {text:"CDEFGH", id:5 },
            {text:"DEFGHI", id:6 },
          ].filter(:item: item.text like pattern) ;
        }
        
        function setText(txt,id) {
          this.candidates.state.popup = false;
          this.input.value = txt;
          this.input.setSelection(0,txt.length); 
          this.input.state.focus = true;
        }
        
      }
    
    
    </script>
  </head>
<body>
  Type "AB" or "CD" or "D":
  <widget|auto-complete>
    <span/>
    <input|text/>
    <popup/>
  </widget>
</body>
</html>
